package sjjg.op;

import java.util.*;

public class BankerAlgorithm {
    //装载原数据
    private List<Map<String, int[]>> all;
    //构造函数
    public BankerAlgorithm() {
    }

    public BankerAlgorithm(List<Map<String, int[]>> all) {
        this.all = all;
    }

    //算法方法
    public void request(int pid,String inSource) {
        //封装request请求
        Request request = new Request(pid, inSource.toCharArray());
        //获得i进程的map集合
        Map<String, int[]> map = all.get(request.pid);
        //进行多步判断
        int[] needs = map.get("Need");
        for (int i = 0; i < needs.length; i++) {
            if (request.eachSource[i] > needs[i]) {
                System.err.println("所需超过最大...");
                return;
            }
        }
        int[] availables = all.get(0).get("Available");
        for (int i = 0; i < availables.length; i++) {
            if (request.eachSource[i] > availables[i]) {
                System.err.println("等待...");
                return;
            }
        }
        //尝试分配
        int[] allocations = map.get("Allocation");
        for (int i = 0; i < allocations.length; i++) {
            availables[i] -= request.eachSource[i];
            allocations[i] += request.eachSource[i];
            needs[i] -= request.eachSource[i];
        }
        //安全检测
        if (!securityCheck(all)) {//失败 回溯结果
            for (int i = 0; i < allocations.length; i++) {
                availables[i] += request.eachSource[i];
                allocations[i] -= request.eachSource[i];
                needs[i] += request.eachSource[i];
            }
            System.out.println("分配失败...");
            return;
        }
        System.out.println("分配成功...");
    }

    public boolean securityCheck(List<Map<String, int[]>> all) {
         boolean[] Finish = new boolean[all.size()];//初值全为false
         int[] Work = Arrays.copyOf(all.get(0).get("Available"), all.get(0).get("Available").length);
         boolean flag = false;
         for (int i = 0; i < all.size(); i++) {
              if (!Finish[i] && isAllLet(all.get(i).get("Need"), Work)) {
                   for (int j = 0; j < Work.length; j++) {
                        Work[j] += all.get(i).get("Allocation")[j];
                   }
                   flag = true;
                   Finish[i] = true;
              }
              if (i == all.size() - 1 && flag) {
                   i = -1;
                   flag = false;
              }
         }
         for (boolean finish : Finish) {
              if (!finish) {
                   return false;
              }
         }
         return true;
    }
    private boolean isAllLet(int[] arr1, int[] arr2) {
        int length = Math.min(arr1.length, arr2.length);
        for (int i = 0; i < length; i++) {
            if (arr1[i] > arr2[i]) {
                return false;
            }
        }
        return true;
    }
    public static void initData(List<Map<String, int[]>> all) {
        Map<String, int[]> p0 = new HashMap<>();
        p0.put("Max", new int[]{7, 5, 3});
        p0.put("Allocation", new int[]{0, 1, 0});
        p0.put("Need", new int[]{7, 4, 3});
        //只需初始化一个
        p0.put("Available", new int[]{3, 3, 2});
        all.add(p0);
        Map<String, int[]> p1 = new HashMap<>();
        p1.put("Max", new int[]{3, 2, 2});
        p1.put("Allocation", new int[]{2, 0, 0});
        p1.put("Need", new int[]{1, 2, 2});
        all.add(p1);
        Map<String, int[]> p2 = new HashMap<>();
        p2.put("Max", new int[]{9, 0, 2});
        p2.put("Allocation", new int[]{3, 0, 2});
        p2.put("Need", new int[]{6, 0, 0});
        all.add(p2);
        Map<String, int[]> p3 = new HashMap<>();
        p3.put("Max", new int[]{2, 2, 2});
        p3.put("Allocation", new int[]{2, 1, 1});
        p3.put("Need", new int[]{0, 1, 1});
        all.add(p3);
        Map<String, int[]> p4 = new HashMap<>();
        p4.put("Max", new int[]{4, 3, 3});
        p4.put("Allocation", new int[]{0, 0, 2});
        p4.put("Need", new int[]{4, 3, 1});
        all.add(p4);
    }

    //内部类 封装request请求
    static class Request {
        private int pid;
        private int[] eachSource;

        public Request(int pid, char[] inSource) {
            this.pid = pid;
            eachSource = new int[inSource.length];
            for (int i = 0; i < inSource.length; i++) {
                eachSource[i] = inSource[i] - 48;
            }
        }
    }

    //main方法测试
    public static void main(String[] args) {
         List<Map<String, int[]>> all = new ArrayList<>();
         //初始化数据
         initData(all);
         //准备算法对象
         BankerAlgorithm bankerAlgorithm = new BankerAlgorithm(all);
         //发送请求
         while (true) {
              Scanner scanner = new Scanner(System.in);
              System.out.println("请输入进程id...");
              int pid = scanner.nextInt();
              if (pid < 0) break;
              System.out.println("请输入为该进程分配各类资源数目...");
              String inSource = scanner.next();
              bankerAlgorithm.request(pid, inSource);
         }

    }
}
